/*
* Copyright 2011 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/
package org.etherframework.wire
{
	import flash.utils.getDefinitionByName;
	
	import org.etherframework.IEther;
	import org.etherframework.core.bridge.IBridgeFacades;
	import org.etherframework.core.common.Ether;
	import org.etherframework.core.common.IObjectProcessor;
	import org.etherframework.core.common.ether_internal;
	import org.etherframework.core.context.Context;
	import org.etherframework.core.reflection.Metadata;
	import org.etherframework.core.reflection.MetadataInfo;
	import org.etherframework.core.reflection.MetadataProperty;
	import org.etherframework.core.reflection.Metatag;
	import org.etherframework.wire.metadata.IntrinsicMetatags;
	import org.etherframework.wire.metadata.MetadataManager;
	
	public class ObjectProcessor implements IObjectProcessor
	{
		private var _metadataManager:MetadataManager;
		private var _intrinsicMetatags:Vector.<String>;
		private var _useIntrinsicProcessors:Boolean;
		
		public function ObjectProcessor(metadataManager:MetadataManager, 
										intrinsicMetatags:Vector.<String>) 
		{
			_metadataManager = metadataManager;
			_intrinsicMetatags = intrinsicMetatags;
			_useIntrinsicProcessors = intrinsicMetatags ? Boolean(intrinsicMetatags.length) : false;
		}
		
		public function process(target:Object, ether:IEther, facade:IBridgeFacades):void
		{
			if (target is Class && _useIntrinsicProcessors)
			{
				const metaInfo:MetadataInfo = _metadataManager.getMetadataInfo(target);
				const metatag:Metatag = metaInfo.getMetatag(IntrinsicMetatags.CONTEXT);
				const items:Vector.<Metadata> = metatag.classMetadata;
				const metadata:Metadata = items ? items[0] : null;
				const prop:MetadataProperty = metadata.getProperty("source");
				
				// TODO: Think about intrinsic metatags
				if (metadata && !prop)
					throw new Error("Intrinsic metatag [Context] specified for class "+metaInfo.className+
						" must have \"source\" property with value poining to a class.");
				
				if (metadata)
				{
					try {
						var context:Context = null;
						const type:Class = getDefinitionByName(prop.value) as Class;
						context = Context(new type());
						
					} catch (e:Error) { throw new Error("Source \""+prop.value+"\" for intrinsic metatag " +
						"[Context] specified for class "+metaInfo.className+" could not be found."); }
					
					Ether(ether).ether_internal::_context = context;
				}
			}
		}
	}
}